<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
	<title>基础：10、组件 Prop</title>
	<script type="text/javascript" src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
	<div id="app">
		<child v-bind:message="msg"></child><br/>
		<child message="msg test1"></child><br/>
		<child message="msg test2"></child>
	</div><br/>

	<div id="app2">
		<!-- <child2 myMessage="test case1"></child2> -->
		<child2 v-bind:my-message="msg"></child2>
	</div><br/>

	<div id="app3">
		<input v-model="parentMsg"><br/>
		<child2 :my-message="parentMsg"></child2>
	</div><br/>

	<div id="app4">
		<child3 :message="msg"></child3><br/>
	</div>

	<script type="text/javascript">
		// 1、父组件通过子组件的props属性向下传递数据给子组件
		// (1)定义一个全局组件
		Vue.component('child',{
			// 声明props，这里为['message']表示父组件可以把数据绑定给这里定义的子组件的message属性，
			// 这样使用这个全局组件进行实例化的子组件就能接收到父组件的数据了
			props: ['message'],
			template: '<span>{{ message }}</span>'
		})

		// (2)在被实例化的元素中使用上面定义的child组件，并将数据传递给子组件
		var vm = new Vue({
			el: '#app',
			data: {
				msg: 'hello vue!'
			}
		})

		// 2、驼峰标识的props在使用中会自动转换为短横线隔开式
		// 可以发现在元素'#app2'中使用驼峰标识属性的child2标签数据模板无法显示，并且会报警
		// 而使用短横线标识属性的child2标签数据模板显示成功
		Vue.component('child2',{
			props: ['myMessage'],
			template: '<span>{{ myMessage }}</span>'
		})		

		var vm2 = new Vue({
			el: '#app2',
			data: {
				msg: 'test case2'
			}
		})

		// 3、动态Prop
		// 在上面的例子中我们绑定父组件中到子组件中的数据都是固定的
		// 如何实现动态的数据绑定呢？很简单，用v-bind + v-model
		// v-bind 的作用是绑定子组件props属性跟父组件之间数据的关系
		// v-model 的作用是让父组件的数据能动态地变化
		// 通过这两个指令，将子组件数据的动态显示和父组件的数据变化隔离开来
		var vm3 = new Vue({
			el: '#app3',
			data: {
				parentMsg: 'app3'
			}
		})

		// 4、字面量语法 vs 动态语法
		// 当传递的属性数据纯粹是字符串时，直接传递即可
		// eg: 这里传递的是字符串1
		// 	   <comp some-prop="1"></comp>
		// 当希望传递的字符串被解析为js表达式时，使用v-bind指令绑定
		// eg: 这里传递的是数字1
		//     <comp :some-prop="1"></comp>
		
		// 5、单向数据流
		// 这个其实也不难理解，这里的单向指数据可以从父组件传递到子组件，但是不能从子组件传递到父组件
		// 实例上，可以把子组件接收到的数据看成是父组件的一个备份，不管你怎么修改它，都不会影响原来父组件的数据
		// 为什么要这样做？父组件下有很多的子组件，如果子组件能修改父组件的数据，
		// 那么跟被修改了的数据相关的其他子组件的数据也会受到影响
		

		// 全局组件中也有data属性，他跟props一样都是跟数据有关的，二者有何区别？
		// 可以这样理解：
		// a、props 相当于父组件跟子组件之间数据的通道
		// b、data 只属于组件所有，定义了局部变量，防止组件的不同实例之间的数据互相干扰
		// c、很多时候，需要对接收的数据进行进一步处理后再显示，这时可以使用computed属性
		// PS.在数据模板中，props、data、computed三者的使用形式一致，所以要保持属性或数据名的区别，否则同名会报异常
		//    eg: data中的 'message2' 变成 'message' 跟props中同名会导致报警		
		Vue.component('child3',{
			props: ['message'],
			template: '<span>{{ message }} - {{ message2 }} - {{ normalizedSize }}</span>',
			data: function(){
				return { message2: 'hello vue!' }
			},
			computed: {
				normalizedSize: function () {
				    return this.message.trim().toLowerCase()
				}
			}
		})
		var vm4 = new Vue({
			el: '#app4',
			data: {
				msg: '  HELLO WORLD！'
			}
		})

		// 6、prop验证
		// 其实就是限定传过来的数据格式，形式为键值对，键名为变量名，键值限定了数据类型、默认值、是否必传、验证函数等
	</script>
</body>
</html>
<!-- 代码均通过测试，有什么纰漏欢迎联系 QQ:1123176978  Wechat:hyhlovehuanong -->